/*
 * @Description:
 * @Version: 2.0
 * @Autor: wiz
 * @Date: 2024-07-18 11:06:42
 * @LastEditors: swc
 * @LastEditTime: 2024-08-24 11:32:06
 */
import { N_cFlowchart, N_oSimpleToolbar } from '@/types';
import { ILayout } from '@antv/layout';
import { CellView, Graph } from '@antv/x6';
import { Selection } from '@antv/x6-plugin-selection';
import { Stencil } from '@antv/x6-plugin-stencil/lib';
import { MouseWheel } from '@antv/x6/lib/graph/mousewheel';
import { Options } from '@antv/x6/lib/graph/options';

class T_graphOpts implements Graph.Options {
  // 画布容器
  container?: HTMLElement = null;

  // 画布宽度，默认使用容器宽度
  width?: number = undefined;

  // 画布宽度，默认使用容器宽度
  height?: number = undefined;

  // 画布的最小最大缩放级别。
  scaling: { min?: number; max?: number } = { min: 0.01, max: 16 };

  // 是否监听容器大小改变，并自动更新画布大小。
  // 默认监听画布容器，也可以指定监听的元素，如 Document
  autoResize?: boolean | Element | Document = true;

  // 画布是否可以拖拽平移，默认禁用。
  panning: boolean | Partial<Graph.PanningManager.Options> = true;

  mousewheel?: boolean | Partial<MouseWheel.Options> = false;

  // 网格，默认使用 10px 的网格，但不绘制网格背景。
  grid?:
    | number
    | boolean
    | (Partial<Graph.GridManager.CommonOptions> &
        Graph.GridManager.DrawGridOptions) = false;

  // 背景，默认不绘制背景。默认false
  background?: false | Graph.BackgroundManager.Options = {
    color: '#F2F7FA'
  };

  // 限制节点移动
  translating: Partial<Options.Translating> = { restrict: false };

  // 嵌套节点，默认禁用
  embedding?: boolean | Partial<Options.Embedding> = false;

  // 连线选项 https://x6.antv.vision/zh/docs/tutorial/basic/interacting/#%E9%80%89%E9%A1%B9-3
  connecting?: Partial<Options.Connecting> = {
    /* 是否允许连接到画布空白位置的点，默认为 true。支持以下两种形式：
      1、boolean 2、((this: Graph, args: ValidateConnectionArgs) => boolean) */
    allowBlank: false,
    /* 是否允许在相同的起始节点和终止之间创建多条边，默认为 true。
        当设置为 false 时，在起始和终止节点之间只允许创建一条边，当设置为 'withPort' 时，
        在起始和终止节点的相同链接桩之间只允许创建一条边（即，起始和终止节点之间可以创建多条边，
        但必须要要链接在不同的链接桩上）。支持以下三种形式：
        1、boolean
        2、withPort
        3、((this: Graph, args: ValidateConnectionArgs) => boolean) 
     */
    allowMulti: false,
    /** 是否允许创建循环连线，即边的起始节点和终止节点为同一节点，默认为 true。支持以下两种形式：
          1、boolean
          2、((this: Graph, args: ValidateConnectionArgs) => boolean)
       */
    allowLoop: false,
    /** 是否允许边链接到节点（非节点上的链接桩），默认为 true。支持以下两种形式：
          1、boolean
          2、((this: Graph, args: ValidateConnectionArgs) => boolean) 
      */
    allowNode: true,
    /*
          是否允许边链接到另一个边，默认为 true。支持以下两种形式：
          1、boolean
          2、((this: Graph, args: ValidateConnectionArgs) => boolean) 
      */
    allowEdge: false,
    /*
          是否允许边链接到链接桩，默认为 true。支持以下两种形式：
          1、boolean
          2、((this: Graph, args: ValidateConnectionArgs) => boolean) 
      */
    allowPort: true,
    // 拖动边时，是否高亮显示所有可用的连接桩或节点，默认值为 false。
    highlight: true,
    // 当连接到节点时，通过 anchor 来指定被连接的节点的锚点，默认值为 center。
    edgeAnchor: 'ratio',
    // 当连接到节点时，通过 anchor 来指定被连接的节点的锚点，默认值为 center。
    anchor: 'center',
    // 路由将边的路径点 vertices 做进一步转换处理，并在必要时添加额外的点，
    // 然后返回处理后的点，默认值为 normal。

    // normal 默认路由，原样返回路径点。
    // orth 正交路由，由水平或垂直的正交线段组成。
    // oneSide 受限正交路由，由受限的三段水平或垂直的正交线段组成。
    // manhattan 智能正交路由，由水平或垂直的正交线段组成，并自动避开路径上的其他节点（障碍）。
    // metro 智能地铁线路由，由水平或垂直的正交线段和斜角线段组成，类似地铁轨道图，并自动避开路径上的其他节点（障碍）。
    // er 实体关系路由，由 Z 字形的斜角线段组成。

    router: 'manhattan',
    /* 当 snap 设置为true时连线的过程中距离节点或者连接桩 
        50px 时会触发自动吸附，可以通过配置 radius 属性自定义触发吸附的距离。
        当 snap 设置为 false 时不会触发自动吸附。默认值为 false。 
      */
    snap: {
      radius: 20
    },
    connector: {
      // normal 简单连接器，用直线连接起点、路由点和终点。
      // smooth 平滑连接器，用三次贝塞尔曲线线连接起点、路由点和终点。
      // rounded 圆角连接器，用直线连接起点、路由点和终点，并在线段连接处用圆弧链接（倒圆角）。
      // jumpover 跳线连接器，用直线连接起点、路由点和终点，并在边与边的交叉处用跳线符号链接。
      name: 'jumpover',
      args: {
        radius: 8
      }
    }
  };

  // 高亮选项
  highlighting: Partial<Options.Highlighting> = undefined;

  // 定制节点和边的交互行为
  interacting?: CellView.Interacting = {
    edgeLabelMovable: false
  };

  // 鼠标移动多少次后才触发连线，或者设置为 onleave 时表示鼠标移出元素时才触发连线。
  magnetThreshold: number | 'onleave' = 0;

  // 触发 'mousemove' 事件之前，允许鼠标移动的次数。
  moveThreshold: number = 0;

  // 当鼠标移动次数超过指定的数字时，将不触发鼠标点击事件。
  clickThreshold: number = 0;

  // 是否禁用浏览器默认右键菜单。
  preventDefaultContextMenu?: boolean = true;

  // 在画布空白位置响应鼠标事件时，是否禁用鼠标默认行为。
  preventDefaultBlankAction?: boolean = true;

  // 是否异步渲染
  async: boolean = true;

  // 是否只渲染可视区域内容
  virtual?: boolean = true;

  // // 当某个连接桩渲染完成时触发的回调。
  // onPortRendered: (args: Options.OnPortRenderedArgs) => void | undefined;

  // // 当边的文本标签渲染完成时触发的回调。
  // onEdgeLabelRendered: (
  //   args: Options.OnEdgeLabelRenderedArgs
  // ) =>
  //   | undefined
  //   | ((args1: Options.OnEdgeLabelRenderedArgs) => void) = undefined;

  // // 是自定义元素的视图。
  // createCellView: (
  //   this: Graph,
  //   cell: Cell
  // ) =>
  //   | typeof CellView
  //   | (new (...args: any[]) => CellView)
  //   | null
  //   | undefined = undefined;

  // 对齐线
  snapline: boolean | object = true;

  // 滚动画布
  scroller: boolean | object = false;

  // 小地图
  minimap: boolean = true;

  // 撤销/重做
  history: boolean | object = true;

  // 剪切板
  clipboard: boolean | object = true;

  // 键盘快捷键
  keyboard: boolean | object = true;

  // 旋转节点
  rotating?: boolean | object = true;

  // 缩放节点
  resizing?: boolean | object = true;

  // 节点和边视图的排序方式
  sorting?: 'none' | 'approx' | 'exact' = 'exact';
}

// 画布配置
class T_conf {
  workMode: N_cFlowchart.I_workMode = 'edit';

  garph?: T_graphOpts;

  // 显示工具 栏
  toolbar: {
    show: boolean;
    // 可选属性，用于配置工具栏的按钮列表。（无：有默认值，有：全部替换）
    list?: N_oSimpleToolbar.I_Conf[] | (() => N_oSimpleToolbar.I_Conf[]);
  };

  rightPanel: {
    show: boolean;
    width: number;
    height?: number;
    opened: boolean;
  };

  // 显示左边容器
  stencil: {
    show: boolean;
    options?: Partial<Stencil.Options>;
  };

  // https://x6.antv.vision/zh/docs/tutorial/advanced/layout/#gatsby-focus-wrapper
  layout: ILayout.LayoutOptions = {
    type: 'dagre', // 布局类型
    rankdir: 'LR', // 布局的方向。T：top（上）；B：bottom（下）；L：left（左）；R：right（右）
    align: 'UL', // 节点对齐方式。U：upper（上）；D：down（下）；L：left（左）；R：right（右）；undefined (居中)
    // begin:[0,0] , //布局左上角对齐位置 [number,number]
    nodeSize: 50,
    nodesep: 30,
    controlPoints: true // 是否保留布局连线的控制点
    // sortByCombo?: boolean;
    // workerEnabled?: boolean;
    // edgeLabelSpace?: boolean;
    // nodeOrder?: string[];
    // preset?: {
    //     nodes: OutNode[];
    //     edges: any[];
    // };
    // onLayoutEnd?: () => void;
    // nodesepFunc?: ((d?: any) => number) | undefined;
    // ranksepFunc?: ((d?: any) => number) | undefined;
  };

  // https://x6.antv.antgroup.com/tutorial/plugins/selection#%E9%85%8D%E7%BD%AE

  // className                          string                  -  附加样式名，用于定制样式
  // multiple                           boolean                 true  是否启用点击多选，启用后按住 ctrl 或 command 键点击节点实现多选
  // multipleSelectionModifiers         ModifierKey             ['ctrl', 'meta']  用于设置上面点击多选配套的修饰键
  // rubberband                         boolean                 false  是否启用框选节点功能
  // modifiers                          ModifierKey             -  用于设置上面框选配套的修饰键
  // strict                             boolean                 false  选框是否需要完全包围节点时才选中节点
  // movable                            boolean                 true  拖动选框时框选的节点是否一起移动
  // content                            string                  -  设置附加显示的内容
  // filter                             Filter                  -  节点过滤器
  // showNodeSelectionBox               boolean                 false  是否显示节点的选择框
  // showEdgeSelectionBox               boolean                 false  是否显示边的选择框
  // pointerEvents                      node | auto             auto  如果打开 showNodeSelectionBox 时，会在节点上方盖一层元素，导致节点的事件无法响应，此时可以配置 pointerEvents: none 来解决，默认值是 auto
  // eventTypes                         SelectionEventType[]    ['leftMouseDown', 'mouseWheelDown']  用于设置框选的触发事件类型

  selection: Selection.Options = {
    enabled: true,
    rubberband: false,
    showNodeSelectionBox: true,
    showEdgeSelectionBox: true,
    multiple: true,
    multipleSelectionModifiers: ['ctrl', 'meta']
  };

  contextMenu: {
    width: 150;
  };

  // 注册节点
  regNodes?: N_cFlowchart.I_node[] | (() => N_cFlowchart.I_node[]) = undefined;

  // 注册vue Node
  regVueNodes?:
    | N_cFlowchart.I_vueNode[]
    | (() => N_cFlowchart.I_vueNode[]) = undefined;

  // 注册边
  regEdges?: N_cFlowchart.I_edge[] | (() => N_cFlowchart.I_edge[]) = undefined;

  // 注册事件
  regEvent?: Map<
    N_cFlowchart.EVENTS | string,
    (e: N_cFlowchart.I_eventParams) => void
  > = undefined;

  // 注册 工具栏
  regToolbar?:
    | N_oSimpleToolbar.I_Conf[]
    | (() => N_oSimpleToolbar.I_Conf[]) = undefined;

  // 注册 工具栏事件
  regToolbarEvent?: Map<string, N_cFlowchart.I_toolbarEventFun> = undefined;

  // 注册快捷方式
  regShortcuts?: Map<string, N_cFlowchart.I_shortcutsFun> = undefined;

  constructor() {
    this.garph = new T_graphOpts();
    this.garph.mousewheel = {
      enabled: true
    };
    this.toolbar = { show: true };
    this.stencil = {
      show: true,
      options: {
        title: '节点', // 内置i18n
        stencilGraphHeight: 0,
        groups: [
          {
            name: '流程图' // 内置i18n
          }
        ]
      }
    };
  }
}

export default { T_conf, T_graphOpts };
